/***************************************************************
|	File:		Entity.h
|	Author:		Almando R. Santos Jr.
|	Course:		SGD
|	Purpose:	Entity class stores the shared data members
|				for all child game entities
***************************************************************/

#ifndef ENTITY_H
#define ENTITY_H


#include "IEntity.h"						// IEntity type
#include "../SGD Wrappers/SGD_Handle.h"		// HTexture type
#include "../SGD Wrappers/SGD_Event.h"
#include "../SGD Wrappers/SGD_Color.h"
#include "../SGD Wrappers/SGD_Listener.h"

#include "../anim/Animation.h"

/**************************************************************/
// Entity class
//	- parent class of all game entities, stores the shared data members
//	- velocity-based movement
class Entity : public IEntity, public SGD::Listener

{
	/**********************************************************/
	// MUST have a virtual destructor to allow upcasted pointers
	// to trigger children destructors at deallocation
public:
	Entity( void );
protected:
	virtual ~Entity( void );			// VIRTUAL destructor

	
public:
	/**********************************************************/
	// Entity Types:
	enum Type{ENT_BASE, ENT_PLAYER, ENT_WALL, ENT_BALL, ENT_GORBI, ENT_CANNYBLE, ENT_PUP, ENT_PUNCH, ENT_SCORPSPEAR, ENT_ALLY, ENT_PHINT};
	
	/**********************************************************/
	// Interface:
	//	- virtual functions for children classes to override
	virtual void	Update			( float elapsedTime )		override;
	virtual void	Render			( void )					override;

	virtual int		GetType			( void )	const			override	{	return ENT_BASE;	}
	virtual SGD::Rectangle GetRect	( void )	const			override;
	

	
	virtual void	HandleCollision	( const Entity* pOther );
	virtual void	HandleEvent		( const SGD::Event*  pEvent );

	// Children classes CANNOT override a 'final' method.
	virtual void	AddRef			( void )					final;
	virtual void	Release			( void )					final;

	void RotatePlayers(Entity* player, float angle, SGD::Point center);


	// Holds on to the animation the object uses
	CAnimation currAnimation;
	
	/**********************************************************/
	// Accessors:

	SGD::Point			GetPosition		( void ) const									{	return m_ptPosition;	}
	SGD::Point			GetDestPos		( void ) const									{	return m_ptDestPos;		}
	SGD::Vector			GetVelocity		( void ) const									{	return m_vtVelocity;	}
	SGD::Size			GetSize			( void ) const									{	return m_szSize;		}
	float				GetRotation		( void ) const									{	return m_fRotation;		}
	bool				CheckActive		( void ) const									{	return m_bIsActive;		}
	bool				GetAerial		( void ) const									{	return m_bAerial;		}
	bool				IsHeld			( void ) const									{	return m_bIsHeld;		}
	float				GetSmashTimer	( void ) const									{	return m_fSmashStun;	}
	SGD::Vector			GetSmashVel		( void ) const									{	return m_vtSmashVel;	}


	// Mutators:
	void				SetImage		(	SGD::HTexture		img			)			{	m_hImage		= img;			}
	void				SetBounceWav	(	SGD::HAudio			wav			)			{	m_hBounceWav	= wav;			}
	void				SetShotWav		(	SGD::HAudio			wav			)			{	m_hShotWav		= wav;			}
	void				SetHitWav		(	SGD::HAudio			wav			)			{	m_hHitWav		= wav;			}
	void				SetPosition		(	SGD::Point			pos			) 			{	m_ptPosition	= pos;			}
	void				SetDestPos		(	SGD::Point			dPos		) 			{	m_ptDestPos		= dPos;			}
	void				SetShadowPos	(	SGD::Point			shadowPos	)			{	m_ptShadowPos	= shadowPos;	}
	void				SetVelocity		(	SGD::Vector			vel			) 			{	m_vtVelocity	= vel;			}
	void				SetAerialVel	(	SGD::Vector			aVel		) 			{	m_vtAerialVel	= aVel;			}
	void				SetSmashVel		(	SGD::Vector			sVel		)			{	m_vtSmashVel	= sVel;			}
	void				SetSize			(	SGD::Size			size		) 			{	m_szSize		= size;			}
	void				SetRotation		(	float				rad			)			{	m_fRotation		= rad;			}
	void				SetSmashTimer	(	float				sTime		)			{	m_fSmashStun	= sTime;		}
	void				ToggleActive	(	bool				onOff		)			{	m_bIsActive		= onOff;		}
	void				SetHeld			(	bool				held		)			{	m_bIsHeld		= held;			}
	void				SetColor		(	SGD::Color			color		)			{	m_TempColor		= color;		}
	void				SetAerial		(	bool				a			)			{	m_bAerial		= a;			}
	 

protected:
	/**********************************************************/
	// members:
	
	SGD::HTexture		m_hImage		= SGD::INVALID_HANDLE;			// image handle
	SGD::HAudio			m_hBounceWav	= SGD::INVALID_HANDLE;			// bounce handle
	SGD::HAudio			m_hShotWav		= SGD::INVALID_HANDLE;			// bounce handle
	SGD::HAudio			m_hHitWav		= SGD::INVALID_HANDLE;			// bounce handle
	SGD::Point			m_ptShadowPos;									// 2D position to make a shadow that can move independantly of the entity
	SGD::Point			m_ptPosition	= SGD::Point{ 0, 0 };			// 2D position
	SGD::Point			m_ptDestPos;									// 2D position where the entity will land when thrown
	SGD::Vector			m_vtVelocity	= SGD::Vector{ 0, 0 };			// 2D velocity
	SGD::Vector			m_vtAerialVel	= SGD::Vector{0, 0};			// 2D velocity for when aerial
	SGD::Vector			m_vtSmashVel;
	SGD::Size			m_szSize		= SGD::Size{0, 0};				// 2D size
	float				m_fRotation		= 0.0f;							// angle in radians
	float				m_fSmashStun	= 0.0f;
	float				m_fHeight		= -0.01f;							// Height after being thrown
	bool				m_bAerial		= false;						// whether or not the object is in the aerial state
	bool				m_bIsActive		= true;							// Whether the object is rendered and can collide
	bool				m_bIsHeld;
	SGD::Color			m_TempColor;									// Temporary variable to show that things happen
private:
	/**********************************************************/
	// reference count
	unsigned int		m_unRefCount	= 1;	// calling 'new' gives the prime reference
};

#endif //ENTITY_H
